﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Mathematics;

namespace NetTopologySuite.Algorithm
{
	public static class CGAlgorithmsDD
	{
		public static int OrientationIndex(Coordinate p1, Coordinate p2, Coordinate q)
		{
			int num = CGAlgorithmsDD.OrientationIndexFilter(p1, p2, q);
			if (num <= 1)
			{
				return num;
			}
			DD x = DD.ValueOf(p2.X) - p1.X;
			DD y = DD.ValueOf(p2.Y) - p1.Y;
			DD x2 = DD.ValueOf(q.X) - p2.X;
			DD y2 = DD.ValueOf(q.Y) - p2.Y;
			return CGAlgorithmsDD.SignOfDet2x2(x, y, x2, y2);
		}

		public static int SignOfDet2x2(DD x1, DD y1, DD x2, DD y2)
		{
			DD dd = x1.Multiply(y2).Subtract(y1.Multiply(x2));
			if (dd.IsZero)
			{
				return 0;
			}
			if (dd.IsNegative)
			{
				return -1;
			}
			return 1;
		}

		private static int OrientationIndexFilter(Coordinate pa, Coordinate pb, Coordinate pc)
		{
			double num = (pa.X - pc.X) * (pb.Y - pc.Y);
			double num2 = (pa.Y - pc.Y) * (pb.X - pc.X);
			double num3 = num - num2;
			double num4;
			if (num > 0.0)
			{
				if (num2 <= 0.0)
				{
					return CGAlgorithmsDD.Signum(num3);
				}
				num4 = num + num2;
			}
			else
			{
				if (num >= 0.0)
				{
					return CGAlgorithmsDD.Signum(num3);
				}
				if (num2 >= 0.0)
				{
					return CGAlgorithmsDD.Signum(num3);
				}
				num4 = -num - num2;
			}
			double num5 = 1E-15 * num4;
			if (num3 >= num5 || -num3 >= num5)
			{
				return CGAlgorithmsDD.Signum(num3);
			}
			return 2;
		}

		private static int Signum(double x)
		{
			if (x > 0.0)
			{
				return 1;
			}
			if (x < 0.0)
			{
				return -1;
			}
			return 0;
		}

		public static Coordinate Intersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			DD lhs = (DD.ValueOf(q2.Y) - DD.ValueOf(q1.Y)) * (DD.ValueOf(p2.X) - DD.ValueOf(p1.X));
			DD rhs = (DD.ValueOf(q2.X) - DD.ValueOf(q1.X)) * (DD.ValueOf(p2.Y) - DD.ValueOf(p1.Y));
			DD rhs2 = lhs - rhs;
			DD lhs2 = (DD.ValueOf(q2.X) - DD.ValueOf(q1.X)) * (DD.ValueOf(p1.Y) - DD.ValueOf(q1.Y));
			DD rhs3 = (DD.ValueOf(q2.Y) - DD.ValueOf(q1.Y)) * (DD.ValueOf(p1.X) - DD.ValueOf(q1.X));
			DD rhs4 = (lhs2 - rhs3) / rhs2;
			double x = (DD.ValueOf(p1.X) + (DD.ValueOf(p2.X) - DD.ValueOf(p1.X)) * rhs4).ToDoubleValue();
			DD lhs3 = (DD.ValueOf(p2.X) - DD.ValueOf(p1.X)) * (DD.ValueOf(p1.Y) - DD.ValueOf(q1.Y));
			DD rhs5 = (DD.ValueOf(p2.Y) - DD.ValueOf(p1.Y)) * (DD.ValueOf(p1.X) - DD.ValueOf(q1.X));
			DD rhs6 = (lhs3 - rhs5) / rhs2;
			double y = (DD.ValueOf(q1.Y) + (DD.ValueOf(q2.Y) - DD.ValueOf(q1.Y)) * rhs6).ToDoubleValue();
			return new Coordinate(x, y);
		}

		private const double DoublePrecisionSafeEpsilon = 1E-15;
	}
}
